Skip to content

CORS: add Vary: Origin when the answer depends on the origin, warn on '*' with credentials, add an origin matcher - #1613

Merged
thboileau-git merged 1 commit into
2.7from
fix/cors-2.7
Oct 31, 2026
Merged

thboileau-git merged 1 commit into
2.7from
fix/cors-2.7

Conversation

@thboileau-git

Copy link
Copy Markdown
Collaborator

The aim

Refs #1611

Make CORS safe behind shared caches and with credentials, following the Fetch standard (CORS protocol, "CORS protocol and HTTP caches") and RFC 9110 section 12.5.5.

  • Vary: Origin was never sent, so a shared cache could serve the response built for one origin to another, or serve a response without CORS headers to a CORS request.
  • * allowed together with credentials makes the filter echo any request origin with Access-Control-Allow-Credentials: true.
  • Only exact origins (or *) can be allowed.

The solution

  • CorsResponseHelper: Vary: Origin is added on every response when the answer depends on the origin (credentials, or allowed origins without *), including requests without Origin. A static * without credentials sends no Vary, as recommended by Fetch.
  • CorsFilter: logs a warning when * is allowed with credentials (behaviour unchanged in 2.7; 3.0 rejects it).
  • New opt-in setAllowedOriginMatcher(Predicate<String>) on CorsService, CorsFilter and CorsResponseHelper (default none). The response always carries the exact request origin. Only effective when the allowed origins don't contain *.
  • Javadoc: Fetch standard instead of the W3C draft, plus a note on credentials.

Reproduction

curl -i -H 'Origin: https://a.example' <url> with CorsService.setAllowedOrigins({"https://a.example"}): the response now has Vary: Origin, also without the Origin header.

Check-list

  • PR size
    • Under 300 lines ✅
    • Can't be split without complicating the process even more
  • Tests
    • Added
  • Doc
    • Added (changes.md, Javadoc)
  • Reviewer
    • Asked for a review

Companion PR for 3.0, where * with credentials is rejected.

🤖 Generated with Claude Code

… '*' with credentials, add an origin matcher

- Vary: Origin is added when the CORS answer depends on the request origin
  (origin allow-list or credentials), including for requests without Origin;
  a static '*' without credentials sends no Vary (Fetch standard).
- A warning is logged when '*' is allowed together with credentials.
- Optional origin matcher (setAllowedOriginMatcher), off by default.
- Javadoc references the Fetch standard instead of the W3C CORS draft.

Refs #1611

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
@sonarqubecloud

Copy link
Copy Markdown

@thboileau-git
thboileau-git merged commit d1c8839 into 2.7 Oct 31, 2026
6 checks passed
@thboileau-git
thboileau-git deleted the fix/cors-2.7 branch October 31, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants